/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package session;

import event.SendEvent;
import event.StatusEvent;
import java.util.ArrayList;
import net.sf.appia.core.Direction;
import net.sf.appia.core.Event;
import net.sf.appia.core.Layer;
import net.sf.appia.core.events.channel.ChannelClose;
import net.sf.appia.core.events.channel.ChannelInit;
import net.sf.appia.protocols.common.RegisterSocketEvent;
import timer.*;
import util.Debug;

/**
 *
 * @author Welington
 */
public class StubbornSession extends CustomSession implements ITimerTask {

    private ArrayList<SendEvent> sent = new ArrayList<SendEvent>();
    private final long TIMEOUT_INTERVAL = 1000;

    public StubbornSession(Layer layer) {
        super(layer);
        current = getClass();
    }

    @Override
    public void handle(Event event) {
        if (event instanceof ChannelInit) {
            handleInit((ChannelInit) event);
        } else if (event instanceof ChannelClose) {
            handleCloseChannel((ChannelClose) event);
        } else if (event instanceof SendEvent) {
            if (event.getDir() == Direction.UP)
                handleDeliveryEvent((SendEvent) event);
            else
                handleSendEvent((SendEvent) event);
        } else if (event instanceof RegisterSocketEvent) {
            handleRegisterSocket((RegisterSocketEvent) event);
        }else if (event instanceof StatusEvent) {
            handleStatusEvent((StatusEvent) event);
        }
    }

    /**
     * upon event <sl, Init> do
     *      sent := ∅;
     *      starttimer(Δ);
     * @param event 
     */
    @Override
    protected void handleInit(ChannelInit event) {
        debug.print(Debug.LOG, current, "handleInit(ChannelInit event)");
        sendEvent(event);

        sent.clear();

//        TimeController tc = TimeController.getInstance();
//        tc.register(this, TIMEOUT_INTERVAL);
    }

    /**
     * upon event Timeoutdo
     *      forall (q,m) ∈ sent do
     *          trigger <ﬂl, Send | q, m>;
     *      starttimer(Δ);
     */
    @Override
    public void onTimeout() {
        debug.print(Debug.LOG, current, "onTimeout()");

        for (SendEvent e : sent) {
            sendAsyncEvent(e, e.getChannel(), e.getDir());
        }
    }

    private void handleCloseChannel(ChannelClose event) {
        debug.print(Debug.LOG, current, "handleCloseChannel(ChannelClose event)");
        sendEvent(event);
    }

    private void handleDeliveryEvent(SendEvent event) {
        debug.print(Debug.LOG, current, "handleDeliveryEvent(SendEvent event)");
        sendEvent(event);
    }

    private void handleRegisterSocket(RegisterSocketEvent event) {
        debug.print(Debug.LOG, current, "handleRegisterSocket(RegisterSocketEvent event)");
        sendEvent(event);
    }

    /**
     * upon event <sl, Send | q, m> do
     *      trigger <ﬂl, Send | q, m>;
     *      sent := sent ∪{(q,m)};
     * @param event The event to be sent
     */
    private void handleSendEvent(SendEvent event) {
        debug.print(Debug.LOG, current, "handleSendEvent(SendEvent event)");
        sendEvent(event);

        sent.add(event);
    }

    private void handleStatusEvent(StatusEvent event) {
        debug.print(Debug.LOG, current, "handleStatusEvent(StatusEvent event)");
        sendEvent(event);
    }
}
